/**
 * 
 */
package org.swing.utility.jai.imgio;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Date;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
/**
 * @author lqnhu
 *
 */
public class ImageHelper {
	 /** 
     * * The image file read 
     *  
     * @param srcImgPath 
     * @return 
     */  
    private static BufferedImage InputImage(String srcImgPath) throws RuntimeException {  
  
        BufferedImage srcImage = null;
        FileInputStream in = null;
        try {  
            // BufferedImage object structure  
            File file = new File(srcImgPath);  
            in = new FileInputStream(file);  
            byte[] b = new byte[5];  
            in.read(b);  
            srcImage = javax.imageio.ImageIO.read(file);  
        } catch (IOException e) {  
        	e.printStackTrace();  
        	throw new RuntimeException("Read the image file error!", e);
        } finally {
        	if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					throw new RuntimeException("Read the image file error!", e);
				}
			}
        }
        return srcImage;  
    }  
  
    /** 
     * * The pictures in the specified image size, source image quality compressed (the default weight of 1) 
     *  
     * @param srcImgPath 
     *            :The source image path 
     * @param outImgPath 
     *            :The compression of image path output 
     * @param new_w 
     *            :The compressed image width 
     * @param new_h 
     *            :The compressed image is high 
     */  
    public static void resize(String srcImgPath, String outImgPath,  
            int new_w, int new_h) {  
        resize(srcImgPath, outImgPath, new_w, new_h, 1F);  
    }  
  
    /** 
     * The pictures in the size and proportion, the specified source image quality (the default compression quality of 1) 
     *  
     * @param srcImgPath 
     *            :The source image path 
     * @param outImgPath 
     *            :The compression of image path output 
     * @param ratio 
     *            :The proportion of the compressed image size 
     * @param per 
     *            :Percentage 
     */  
    public static void resize(String srcImgPath, String outImgPath,  
            float ratio) {  
        resize(srcImgPath, outImgPath, ratio, 1F);  
    }  
  
    /** 
     * Put them in a specified maximum length or width to compress pictures (the default weight of 1) 
     *  
     * @param srcImgPath 
     *            :The source image path 
     * @param outImgPath 
     *            :The compression of image path output 
     * @param maxLength 
     *            :The maximum length or width. 
     * @param per 
     *            :The picture quality 
     */  
    public static void resize(String srcImgPath, String outImgPath,  
            int maxLength) {  
        resize(srcImgPath, outImgPath, maxLength, 1F);  
    }  
  
    /** 
     * * The pictures in the specified image size, image compression quality 
     *  
     * @param srcImgPath 
     *            :The source image path 
     * @param outImgPath 
     *            :The compression of image path output 
     * @param new_w 
     *            :The compressed image width 
     * @param new_h 
     *            :The compressed image is high 
     * @param per 
     *            :Percentage 
     * @author cevencheng
     */  
    public static void resize(String srcImgPath, String outImgPath,  
            int new_w, int new_h, float per) {  
        // Get the picture  
        BufferedImage src = InputImage(srcImgPath);  
        int old_w = src.getWidth();  
        // Get the source map width  
        int old_h = src.getHeight();  
        // Get the source map length  
        // According to the original size of the generated blank canvas  
        BufferedImage tempImg = new BufferedImage(old_w, old_h,  
                BufferedImage.TYPE_INT_RGB);  
        // Image generation in the new canvas thumbnail  
        Graphics2D g = tempImg.createGraphics();  
        g.setColor(Color.white);  
        g.fillRect(0, 0, old_w, old_h);  
        g.drawImage(src, 0, 0, old_w, old_h, Color.white, null);  
        g.dispose();  
        BufferedImage newImg = new BufferedImage(new_w, new_h,  
                BufferedImage.TYPE_INT_RGB);  
        newImg.getGraphics().drawImage(  
                tempImg.getScaledInstance(new_w, new_h, Image.SCALE_SMOOTH), 0,  
                0, null);  
        // Call the method of output image file  
        outImage(outImgPath, newImg, per);  
    }  
  
    /** 
     * * The pictures in proportion to the size of the specified image quality, compression 
     *  
     * @param srcImgPath 
     *            :The source image path 
     * @param outImgPath 
     *            :The compression of image path output 
     * @param ratio 
     *            :The proportion of the compressed image size 
     * @param per 
     *            :Percentage 
     * @author cevencheng
     */  
    public static void resize(String srcImgPath, String outImgPath,  
            float ratio, float per) {  
        // Get the picture  
        BufferedImage src = InputImage(srcImgPath);  
        int old_w = src.getWidth();  
        // Get the source map width  
        int old_h = src.getHeight();  
        // Get the source map length  
        int new_w = 0;  
        // The new width  
        int new_h = 0;  
        // The new long  
        BufferedImage tempImg = new BufferedImage(old_w, old_h,  
                BufferedImage.TYPE_INT_RGB);  
        Graphics2D g = tempImg.createGraphics();  
        g.setColor(Color.white);  
        // The color from the original drawings on g.fillRect(0, 0, old_w, old_h);  
        g.drawImage(src, 0, 0, old_w, old_h, Color.white, null);  
        g.dispose();  
        // According to the picture size compression ratio obtained size new_w NEW = (int) Math.round(old_w * ratio);  
        new_h = (int) Math.round(old_h * ratio);  
        BufferedImage newImg = new BufferedImage(new_w, new_h,  
                BufferedImage.TYPE_INT_RGB);  
        newImg.getGraphics().drawImage(  
                tempImg.getScaledInstance(new_w, new_h, Image.SCALE_SMOOTH), 0,  
                0, null);  
        // Call the method of output image file OutImage(outImgPath, newImg, per);  
    }  
  
    /** 
     * <b>
     * Specifies the maximum length or width to the compression of image
     * 	Recommend the use of this method 
     * </b>
     * @param srcImgPath 
     *            :The source image path 
     * @param outImgPath 
     *            :The compression of image path output 
     * @param maxLength 
     *            :The maximum length or width. 
     * @param per 
     *            :The picture quality 
     * @author cevencheng
     */  
    public static void resize(String srcImgPath, String outImgPath,  
            int maxLength, float per) {  
        // Get the picture  
        BufferedImage src = InputImage(srcImgPath);  
        int old_w = src.getWidth();  
        // Get the source map width  
        int old_h = src.getHeight();  
        // Get the source map length  
        int new_w = 0;  
        // The new width  
        int new_h = 0;  
        // The new long  
        BufferedImage tempImg = new BufferedImage(old_w, old_h,  
                BufferedImage.TYPE_INT_RGB);  
        Graphics2D g = tempImg.createGraphics();  
        g.setColor(Color.white);  
        // The color from the image drawings  
        g.fillRect(0, 0, old_w, old_h);  
        g.drawImage(src, 0, 0, old_w, old_h, Color.white, null);  
        g.dispose();  
        // According to the size of image compression ratio obtained new dimensions  
        if (old_w > old_h) {  
            // Image to zoom ratio  
            new_w = maxLength;  
            new_h = (int) Math.round(old_h * ((float) maxLength / old_w));  
        } else {  
            new_w = (int) Math.round(old_w * ((float) maxLength / old_h));  
            new_h = maxLength;  
        }  
        BufferedImage newImg = new BufferedImage(new_w, new_h,  
                BufferedImage.TYPE_INT_RGB);  
        newImg.getGraphics().drawImage(  
                tempImg.getScaledInstance(new_w, new_h, Image.SCALE_SMOOTH), 0,  
                0, null);  
        // Call the method of output image file  
        outImage(outImgPath, newImg, per);  
    }  
    
    /**
     * To compress the pictures into the specified width, height scaling
     * 
     * @param srcImgPath
     * @param outImgPath
     * @param width
     * @param per
     */
    public static void resizeFixedWidth(String srcImgPath, String outImgPath,  
    		int width, float per) {  
    	// Get the picture  
    	BufferedImage src = InputImage(srcImgPath);  
    	int old_w = src.getWidth();  
    	// Get the source map width  
    	int old_h = src.getHeight();  
    	// Get the source map length  
    	int new_w = 0;  
    	// The new width  
    	int new_h = 0;  
    	// The new long  
    	BufferedImage tempImg = new BufferedImage(old_w, old_h,  
    			BufferedImage.TYPE_INT_RGB);  
    	Graphics2D g = tempImg.createGraphics();  
    	g.setColor(Color.white);  
    	// The color from the image drawings  
    	g.fillRect(0, 0, old_w, old_h);  
    	g.drawImage(src, 0, 0, old_w, old_h, Color.white, null);  
    	g.dispose();  
    	// According to the size of image compression ratio obtained new dimensions  
    	if (old_w > old_h) {  
    		// Image to zoom ratio  
    		new_w = width;  
    		new_h = (int) Math.round(old_h * ((float) width / old_w));  
    	} else {  
    		new_w = (int) Math.round(old_w * ((float) width / old_h));  
    		new_h = width;  
    	}  
    	BufferedImage newImg = new BufferedImage(new_w, new_h,  
    			BufferedImage.TYPE_INT_RGB);  
    	newImg.getGraphics().drawImage(  
    			tempImg.getScaledInstance(new_w, new_h, Image.SCALE_SMOOTH), 0,  
    			0, null);  
    	// Call the method of output image file  
    	outImage(outImgPath, newImg, per);  
    }  
  
    /** 
     * * Image files will be output to the specified path, and set the compression quality 
     *  
     * @param outImgPath 
     * @param newImg 
     * @param per 
     * @author cevencheng
     */  
    private static void outImage(String outImgPath, BufferedImage newImg, float per) {  
        // Determine whether there is a folder path output, does not exist then create  
        File file = new File(outImgPath);  
        if (!file.getParentFile().exists()) {  
            file.getParentFile().mkdirs();  
        }
        // The output to a file stream
        FileOutputStream fos = null;
        try {  
            fos = new FileOutputStream(outImgPath);  
            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fos);  
            JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(newImg);  
            // Compression quality  
            jep.setQuality(per, true);  
            encoder.encode(newImg, jep);  
            fos.close();  
        } catch (Exception e) { 
        	throw new RuntimeException(e);
        } finally {
        	if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
        }
    }  
  
    /**
     * Picture cutting tool method
     * 
     * @Param srcfile source
     * @After the param outfile shear pictures
     * @Param x shear X vertex coordinates
     * @Param y shear Y vertex coordinates
     * @Param width shear zone width
     * @Param height shear zone height
     * 
     * @throws IOException
     * @author cevencheng
     */
	public static void cut(File srcfile, File outfile, int x, int y, int width, int height) throws IOException {
		FileInputStream is = null;
		ImageInputStream iis = null;
		try {
			// Read the image file
			is = new FileInputStream(srcfile);

			/*
			 * Return contains all the currently registered ImageReader Iterator, these ImageReader claims to be able to decode the specified format. 
			 * Parameters: formatName - contains informal format name. (such as "JPEG" or "TIFF") etc. 
			 */
			Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName("jpg");
			ImageReader reader = it.next();
			// Get a picture stream
			iis = ImageIO.createImageInputStream(is);

			/*
			 * <p>Iis: read the source.True: only forward search </p>. It will be marked as' only forward search'. 
			 * This setting means that the images contained in the input source will only read sequentially by, may allow reader to avoid cache data contains the image associated with a previously read the input part. 
			 */
			reader.setInput(iis, true);

			/*
			 * <p>Describes how to decode the < convection; p>. Used to specify how the input from the Java Image I in/O
			 * Framework in the context of stream converting an image or set of images. For the specific image format plugins will realize from the ImageReader
			 * Examples of ImageReadParam return in getDefaultReadParam method. 
			 */
			ImageReadParam param = reader.getDefaultReadParam();

			/*
			 * Image cropping area. Rectangle specifies an area coordinates in space, through the Rectangle object
			 * The top left vertex coordinates (x, y), the width and height can be defined in this area. 
			 */
			Rectangle rect = new Rectangle(x, y, width, height);

			// To provide a BufferedImage, used in the decoding of the pixel data object. 
			param.setSourceRegion(rect);

			/*
			 * Use the provided ImageReadParam read through the object index specified in imageIndex, and use it as a complete
			 * BufferedImage returns. 
			 */
			BufferedImage bi = reader.read(0, param);

			// Save the new picture
			ImageIO.write(bi, "jpg", outfile);
		} finally {
			if (is != null) {
				is.close();
			}
			if (iis != null) {
				iis.close();
			}
		}
    }
    
    public static void main(String args[]) throws Exception {  
        String srcImg = "c:/zuidaima/car_2.jpg";  
        String tarDir = "c:/zuidaima/newImg/";  
        URL url = ImageUtil.class.getResource("src-2012.jpg");
        File srcfile = new File(url.toURI());
        System.out.println(url);
        System.out.println(srcfile.exists() + ", dir=" + srcfile.getParent());
        tarDir = srcfile.getParent();
        srcImg = srcfile.getPath();
        System.out.println("srcImg=" + srcImg);
        long startTime = new Date().getTime();  
        resize(srcImg, tarDir + "car_1_maxLength_1-200px.jpg", 200);  
//        Tosmallerpic(srcImg, tarDir + "car_1_maxLength_2.jpg", 0.5F);  
        resize(srcImg, tarDir + "car_1_maxLength_3.jpg", 400, 500);  
        resize(srcImg, tarDir + "car_1_maxLength_4-400x400.jpg", 220, 220);  
        resize(srcImg, tarDir + "car_1_maxLength_11-220px-yinhui.jpg", 220, 0.7F);  
//        Tosmallerpic(srcImg, tarDir + "car_1_maxLength_22.jpg", 0.5F, 0.8F);  
        resize(srcImg, tarDir + "car_1_maxLength_33.jpg", 400, 500, 0.8F);  
        System.out.println(new Date().getTime() - startTime);  
    } 
}
